/*
 * RecordsFilter.java
 *
 * Created on December 16, 2005, 11:35 AM
 *
 */

package biofilter.filters;

import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import biofilter.exceptions.InvalidRecordException;
import biofilter.records.Record;
import biofilter.sources.RecordsSourceIF;


/**
 * To create a base class for filters. 
 * 
 * @author yan, tom, rox
 */

public abstract class RecordsFilter implements RecordsSourceIF {
    protected RecordsSourceIF source;
    protected Record originalRecord;
    protected Record transformedRecord;
    protected LinkedList<Record> originalRecords = new LinkedList<Record>();
    protected LinkedList<Record> transformedRecords = new LinkedList<Record>();
    protected Logger logger = null;
    protected boolean trackOriginalRecords = false;
    protected boolean trackTransformedRecords = false;
    
    /** Creates a new instance of RecordsFilter */
    public RecordsFilter() {
        this(null);
    }
    
    /** Creates a new instance of RecordsFilter 
     * @param rs A records source.
     */
    public RecordsFilter( RecordsSourceIF rs ) {
        super();
	logger = Logger.getLogger(this.getClass().getName());
        
	if(rs!=null) {
            try{
		this.setSource(rs);
            }catch(IllegalArgumentException iae) {
                logger.log(Level.SEVERE, "unable to setSource", iae);
                throw new RuntimeException("could not set source", iae);
            }            
	}
    }
    
    /**
     * To set the source of this filter.
     * @param source The records source containing records to be transformed.
     */
    public void setSource ( Object source ) throws IllegalArgumentException {
        this.source = (RecordsSourceIF) source;
    }
    
    /**
     * To reset the source of this filter.
     */
    public void resetSource() throws IllegalArgumentException {
        this.source.resetSource();
    }
    
    /**
     * Return the originalRecord .
     * @return The original record
     */
    public Record getOriginalRecord() {
        return this.originalRecord;
    }
    
    /**
     * Return the transformed Record.
     * @return The transformed record
     */
    public Record getTransformedRecord() {
        return this.transformedRecord;
    }
    
    /**
     * Return the originialRecords.
     * @return An array of Records that are the set of original records
     * collected up to the current point.
     */
    public Record[] getOriginalRecords() {
        if ( trackOriginalRecords && originalRecords != null) {
	    return this.originalRecords.toArray( new Record[0]);
	}
	else {
            return null;
	}
    }
    
    /**
     * Return the transformed Records.
     * @return An array of Records that are the set of transformed records
     * produced by the filter up to the current point.
     */
    public Record[] getTransformedRecords() {
        if ( trackTransformedRecords && transformedRecords != null) {
	    return this.transformedRecords.toArray( new Record[0]);
	}
	else {
            return null;
	}
    }
    
    /**
     * To provide a structure for doing record transformation in filters.
     * @param r The record to be transformed.
     * @return  The transformed Record
     */
    protected abstract Record transformRecord( Record r ) throws InvalidRecordException;
    
    /**
     * To indicate to the RecordsFilter that originalRecords should be tracked. 
     * This is off by default, because tracking original records uses considerably
     * more memory than not tracking them.  Therefore, this should be used carefully and 
     * only when necessary. 
     * @param trackOriginalRecords This is true if original records should be tracked,
     * false if not and the default is set to false.
     */
    public void trackOriginalRecords( boolean trackOriginalRecords ) {
        this.trackOriginalRecords = trackOriginalRecords;
    }
    
    /**
     * To indicate to the RecordsFilter that transformedRecords should be tracked. 
     * This is off by default, because tracking transformed records uses considerably
     * more memory than not tracking them.  Therefore, this should be used carefully and 
     * only when necessary. 
     * @param trackTransformedRecords This s is true if transformed records should be
     * tracked, false if not and the default is set to true.
     */
    public void trackTransformedRecords( boolean trackTransformedRecords ) {
        this.trackTransformedRecords = trackTransformedRecords;
    }
}

